package cn.wgx.commons.aop;

import cn.wgx.commons.annotation.ApiPermission;
import cn.wgx.commons.util.BaseLogger;
import cn.wgx.commons.util.Servlets;
import cn.wgx.commons.util.SpringContextHolder;
import cn.wgx.commons.util.StringUtils;
import cn.wgx.modules.sys.entity.SysPermission;
import cn.wgx.modules.sys.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.naming.NoPermissionException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 自定义权限过滤器,aop实现,继承shiro权限并增强
 */
@Aspect
@Component
//@Order(200)
@Slf4j
@DependsOn(value = "springContextHolder")//依赖springContextHolder启动完后才能初始化本类
public class ApiPermissionAop {

//    @Value("${spring.profiles.active}")
//    private String devStr = "";

    private static boolean dev;

    static {
        String per = SpringContextHolder.getActiveProfile("spring.profiles.active");

//        dev = "dev".equals(bean.getProperty("spring.profiles.active"));
        dev = "dev".equals(SpringContextHolder.getActiveProfile()) && "true".equals(per);
        if(dev){
            log.warn("ApiPermissionAop: 开发者模式启动,接口过滤器已关闭.");
        }
    }

    //    @Pointcut("@annotation(cn.wgx.commons.annotation.ApiPermission)) || @annotation(org.apache.shiro.authz.annotation.RequiresUser)")
//    private void cutPermission() {}
    @Pointcut("@annotation(cn.wgx.commons.annotation.ApiPermission) " +
            "|| @annotation(org.apache.shiro.authz.annotation.RequiresPermissions)" +
            "|| @annotation(org.apache.shiro.authz.annotation.RequiresAuthentication)" +
            "|| @annotation(org.apache.shiro.authz.annotation.RequiresRoles)")
    private void cutPermission() {
    }

    @Before("cutPermission()")
    public void doPermission(JoinPoint point) throws Exception {
        if(dev){
            //开发模式不鉴权
            return;
        }

        //管理员账户不审核权限
        if (UserUtil.getUser().getUsername().equals("admin")) return;

        MethodSignature ms = (MethodSignature) point.getSignature();
        Method method = ms.getMethod();
        Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof ApiPermission) {
                ApiPermission apiPermission = (ApiPermission) annotation;
                if (!apiPermission.value()) {
                    return;
                }
                break;
            }
        }
        //自定义权限判定
        if (!checkPermission()) {
            throw new NoPermissionException();
        }
    }

    private boolean checkPermission() {
        String path = Servlets.getRequestUri();
        String method = Servlets.getRequest().getMethod();

        boolean pass = false;
        List<SysPermission> sysPermissionList = UserUtil.getPrincipal().getSysPermissions_list();
        if(sysPermissionList == null){
            return false;
        }
        for (SysPermission sysPermission : sysPermissionList) {
            if (path.equals(sysPermission.getUrl()) && method.equals(sysPermission.getMethod().toUpperCase())) {
                pass = true;
                break;
            }
        }
        if (log.isDebugEnabled()) {
            log.debug(path + " | " + method + " | " + UserUtil.getUser().getUsername() + " | " + pass);
        }
        return pass;
    }


    /**
     * 作废
     *
     * @param method
     * @return
     */
    private String getClassRequestMappingPath(Method method) {
        Class clazz = method.getDeclaringClass();
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof RequestMapping) {
                String path[] = ((RequestMapping) annotation).value();
                if (path != null && path.length > 0) {
                    return path[0];
                }
            }
        }
        return StringUtils.EMPTY;
    }
}
